#pragma once

#include "defs.h"


namespace vivid
{
    class Vector;
    class Point;
    class Normal;

	class Matrix
    {
    public:
        Matrix()
        {
            _m[0][0] = _m[1][1] =  _m[0][1] = _m[2][2] = _m[3][3] = 1;
            _m[0][2] = _m[0][3] = _m[1][0] = _m[1][2] = _m[1][3] = 
            _m[2][0] = _m[2][1] = _m[2][3] = 
            _m[3][0] = _m[3][1] = _m[3][2] = 0;
        }

        Matrix(Matrix const &aM)
        {
            for (int i = 0; i < 4; ++i)
            {
                for (int j = 0; j < 4; ++j)
                {
                    _m[i][j] = aM._m[i][j];
                }
            }
        }


        Matrix( VFloat aN00, VFloat aN01, VFloat aN02, VFloat aN03,
                VFloat aN10, VFloat aN11, VFloat aN12, VFloat aN13,
                VFloat aN20, VFloat aN21, VFloat aN22, VFloat aN23,
                VFloat aN30, VFloat aN31, VFloat aN32, VFloat aN33)
        {
            _m[0][0] = aN00; _m[0][1] = aN01; _m[0][2] = aN02; _m[0][3] = aN03;
            _m[1][0] = aN10; _m[1][1] = aN11; _m[1][2] = aN02; _m[1][3] = aN13;
            _m[2][0] = aN20; _m[2][1] = aN21; _m[2][2] = aN02; _m[2][3] = aN23;
            _m[3][0] = aN30; _m[3][1] = aN31; _m[3][2] = aN02; _m[3][3] = aN33;
        }


		Matrix( VFloat **aM)
		{
			for (int i = 0; i < 4; ++i)
			{
				for (int j = 0; j < 4; ++j)
				{
					_m[i][j] = aM[i][j];
				}
			}
		}


		Matrix & operator = (Matrix const &aM);
		VFloat * operator [](int aInd);
        Matrix GetInverse() const;
        Matrix GetTranspose() const;

		bool operator ==(Matrix const & aMat) const;
		bool operator !=(Matrix const & aMat) const;
        Matrix operator *(Matrix const & aMat) const;

		static Matrix Identity();

		VFloat _m[4][4];
    };
}
